﻿
using Framework.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Framework.Components
{
    /// <summary>
    /// 基础产品, 支持字符串转化
    /// </summary>
    public abstract class ProductParser<P>
    {
        protected string regexA = "@";
        protected string regexB = "|";

        public ProductParser() { }

        public ProductParser(string regexA, string regexB)
        {
            this.regexA = regexA;
            this.regexB = regexB;
        }

        /// <summary>
        /// 加密成字符串
        /// </summary>
        protected string ToEncode(P product) { return ToEncode(product, 1.0); }

        /// <summary>
        /// 加密成字符串
        /// </summary>
        protected abstract string ToEncode(P product, double scale);

        /// <summary>
        /// 从字符串中解析出数据
        /// </summary>
        protected abstract P ToDecode(string str);

        /// <summary>
        /// 是否是同类型的资源
        /// </summary>
        public abstract bool IsSameRes(P src, P dst);

        /// <summary>
        /// 合并数据
        /// </summary>
        protected virtual bool Merge(P src, P other) { return false; }

        /// <summary>
        /// 转为字符串
        /// </summary>
        public string ToString(P product)
        {
            return ToEncode(product);
        }

        /// <summary>
        /// 转为字符串
        /// </summary>
        public string ToString(List<P> products)
        {
            return ToString(products, 1.0);
        }

        /// <summary>
        /// 转为字符串
        /// </summary>
        public string ToString(List<List<P>> productList)
        {
            return ToString(productList, 1.0);
        }

        /// <summary>
        /// 转为字符串
        /// </summary>
        public string ToString(List<List<P>> productList, double scale)
        {
            StringBuilder strBdr = new StringBuilder();
            int psize = (productList != null) ? productList.Count : 0;
            for (int i = 0; i < psize; i++)
            {
                if (i > 0) { strBdr.Append(regexA); }
                strBdr.Append(ToString(productList[i], scale));
            }
            return strBdr.ToString();
        }

        /// <summary>
        /// 转为字符串
        /// </summary>
        public string ToString(P[] products, double scale)
        {
            return ToString((products != null) ? products.ToList() : null, scale);
        }

        /// <summary>
        /// 转为字符串
        /// </summary>
        public string ToString(List<P> products, double scale)
        {
            StringBuilder strBdr = new StringBuilder();
            int psize = (products != null) ? products.Count : 0;
            for (int i = 0; i < psize; i++)
            {
                // 处理分割
                if (i > 0) { strBdr.Append(regexB); }
                // 处理数量变化
                P product = products[i];
                strBdr.Append(ToEncode(product, scale));
            }
            return strBdr.ToString();
        }

        /// <summary>
        /// 检测格式是否符合(空也是符合的)
        /// </summary>
        public bool CheckString(string str)
        {
            try
            {
                // 解析没报错就代表成功
                ToProducts(str);
                return true;
            }
            catch (Exception) { }
            return false;
        }

        /// <summary>
        /// 拆分成Product, 格式: type,id,count|type,id,count
        /// </summary>
        /// <returns></returns>
        public List<P> ToProducts(string str) { return ToProducts(str, true); }

        /// <summary>
        /// 拆分成Product, 格式: type,id,count|type,id,count
        /// </summary>
        /// <returns></returns>
        public List<P> ToProducts(string str, bool merge)
        {
            // 空判断
            if (string.IsNullOrEmpty(str))
            {
                return new List<P>(); // 空就是没有
            }

            // 截取拆分
            string[] values = str.Split(new string[] { regexB }, StringSplitOptions.None);
            int vsize = (values != null) ? values.Length : 0;
            if (vsize <= 0)
            {
                return new List<P>(); // 空就是没有
            }

            // 遍历生成
            var ps = new List<P>(vsize);
            for (int i = 0; i < vsize; i++)
            {
                var valueStr = values[i];
                if (string.IsNullOrEmpty(valueStr)) { continue; }
                // 创建产品
                var product = ToDecode(valueStr);
                if (product == null)
                {
                    throw new Exception("解析错误! str=" + str);
                }
                ps.Add(product);
            }

            // 执行合并
            if (merge && vsize >= 2)
            {
                if (!Merge(ps))
                {
                    throw new Exception("整合数据错误!");
                }
            }
            return ps;
        }

        /// <summary>
        /// 整合相同类型的资源
        /// </summary>
        public bool Merge(List<P> products)
        {
            // 检测数量
            int vsize = (products != null) ? products.Count : 0;
            if (vsize <= 1) { return true; }

            // 遍历检测是否存在重复的数据
            for (int i = 0; i < vsize; i++)
            {
                P product = products[i];
                // 遍历检测是否相同
                for (int j = i + 1; j < vsize; j++)
                {
                    P check = products[j];
                    if (!IsSameRes(product, check))
                    {
                        continue;
                    }
                    // 移除当前资源
                    vsize--;
                    products.RemoveAt(j);
                    j--;

                    // 相同资源
                    if (!Merge(product, check)) { return false; }
                }
            }
            return true;
        }

        /// <summary>
        /// 拆分成一个Product, 格式: type,id,count
        /// </summary>
        public P ToProduct(string str)
        {
            var list = ToProducts(str);
            int lsize = (list != null) ? list.Count : 0;
            return (lsize > 0) ? list[0] : default(P);
        }

        /// <summary>
        /// 拆分成Product, 格式: type,id,count|type,id,count
        /// </summary>
        public P[] ToProductArray(string str)
        {
            var ps = ToProducts(str);
            return (ps != null) ? ps.ToArray() : null;
        }

        /// <summary>
        /// 多组奖励, 格式: type,id,count|type,id,count@type,id,count|type,id,count
        /// </summary>
        public List<List<P>> ToProductList(string str)
        {
            // 空判断
            if (string.IsNullOrEmpty(str)) { return new List<List<P>>(); }
            // 截取拆分
            try
            {
                // 拆分字符串
                string[] strs = str.Split(new string[] { regexA }, StringSplitOptions.None);
                int ssize = (strs != null) ? strs.Length : 0;
                // 遍历
                var list = new List<List<P>>(ssize);
                for (int i = 0; i < ssize; i++)
                {
                    var plist = ToProducts(strs[i]);
                    list.Add(plist);
                }
                return list;
            }
            catch (Exception e)
            {
                Log.Error("拆分字符串异常, str:" + str, e);
            }
            return null;
        }
    }



    /// <summary>
    /// 产品接口
    /// </summary>
    public interface IProduct
    {
        /// <summary>
        /// 产品类型
        /// </summary>
        int Type { get; }

        /// <summary>
        /// 产品Id
        /// </summary>
        int Id { get; }

        /// <summary>
        /// 产品数量
        /// </summary>
        long Count { get; }

    }

    /// <summary>
    /// 产品解析器
    /// </summary>
    public class ProductParserT : ProductParser<Product>
    {
        protected override bool Merge(Product src, Product other)
        {
            src.Count += other.Count;
            return true;
        }

        public override bool IsSameRes(Product src, Product dst)
        {
            if (src == null || dst == null) { return false; }
            return (src.Type == dst.Type) && (src.Id == dst.Id);
        }

        protected override Product ToDecode(string str)
        {
            int[] values = StringUtils.SplitTo<int>(str, ",");
            int vsize = (values != null) ? values.Length : 0;
            if (vsize < 3) { return null; }
            // 创建对象
            var product = new Product();
            product.Type = values[0];
            product.Id = values[1];
            product.Count = values[2];
            return product;
        }

        protected override string ToEncode(Product product, double scale)
        {
            long count = (long)(product.Count * scale);
            // 输出字符串
            StringBuilder strBdr = new StringBuilder();
            strBdr.Append(product.Type);
            strBdr.Append(",");
            strBdr.Append(product.Id);
            strBdr.Append(",");
            strBdr.Append(count);
            return strBdr.ToString();
        }
    }

    /// <summary>
    /// 产品对象
    /// </summary>
    public class Product : IProduct
    {
        private static ProductParserT _parser = new ProductParserT();
        public static ProductParserT Parser { get { return _parser; } }

        /// <summary>
        /// 产品类型
        /// </summary>
        public int Type { get; set; }

        /// <summary>
        /// 产品Id
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// 产品数量
        /// </summary>
        public long Count { get; set; }


        public Product(int type, int id, long count)
        {
            Type = type;
            Id = id;
            Count = count;
        }

        public Product() { }

        /// <summary>
        /// 乘法(数量放大N倍, 创建新对象)
        /// </summary>
        /// <param name="scale"></param>
        /// <returns></returns>
        public Product Mult(double scale)
        {
            return new Product(Type, Id, (int)(scale * Count));
        }

        /// <summary>
        /// 判断是否是同类资源, type和id相同即可
        /// </summary>
        public bool IsSameRes(int type, int id)
        {
            return (Type == type) && (Id == id);
        }

        /// <summary>
        /// 判断2个对象是否相同
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public override bool Equals(object obj)
        {
            if (obj == null) { return false; }
            // 检测内存指针是否相等
            if (this == obj) { return true; }
            // 判断类是否相同
            if (GetType() != obj.GetType()) { return false; }
            // 检测测试
            Product other = (Product)obj;
            if (Count != other.Count) { return false; }
            if (Id != other.Id) { return false; }
            if (Type != other.Type) { return false; }
            return true;
        }

        /// <summary>
        /// 获取哈希值
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            const int prime = 31;
            int result = 1;
            result = prime * result + (int)Count;
            result = prime * result + Id;
            result = prime * result + Type;
            return result;
        }


        /// <summary>
        /// 判断是否是同类资源, type和id相同即可
        /// </summary>
        /// <param name="src"></param>
        /// <param name="dst"></param>
        /// <returns></returns>
        public static bool IsSameRes(Product src, Product dst)
        {
            return Parser.IsSameRes(src, dst);
        }

        /// <summary>
        /// 数据放大
        /// </summary>
        /// <param name="products"></param>
        /// <param name="scale"></param>
        public static void Mult(List<Product> products, double scale)
        {
            int psize = (products != null) ? products.Count : 0;
            for (int i = 0; i < psize; i++)
            {
                Product product = products[i];
                product.Count = (int)(product.Count * scale);
            }
        }

        /// <summary>
        /// 数据复制
        /// </summary>
        public static List<P> Copy<P>(List<P> products) where P : Product, new()
        {
            var copys = new List<P>();
            int psize = (products != null) ? products.Count : 0;
            for (int i = 0; i < psize; i++)
            {
                P product = products[i];
                try
                {
                    P copy = new P();
                    copys.Add(copy);
                }
                catch (Exception e)
                {
                    Log.Error("复制Product错误!?", e);
                }
            }
            return copys;
        }

        /// <summary>
        /// 转为字符串
        /// </summary>
        public static string ToString(int type, int id, long count)
        {
            StringBuilder strBdr = new StringBuilder();
            strBdr.Append(type);
            strBdr.Append(",");
            strBdr.Append(id);
            strBdr.Append(",");
            strBdr.Append(count);
            return strBdr.ToString();
        }


    }


}
